package com.jolink.omiis.wechat.schedule;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.jolink.omiis.wechat.SpringContextUtil;
import com.jolink.omiis.wechat.api.CSMessageBuilder;
import com.jolink.omiis.wechat.api.IWeChatBrokerMessage;
import com.jolink.omiis.wechat.api.WeChatServiceApiUtil;
import com.jolink.omiis.wechat.inner.ConversationType;
import com.jolink.omiis.wechat.message.type.MessageType;
import com.jolink.omiis.wechat.message.type.SenderRole;
import com.jolink.omiis.wechat.util.CacheUtil;
import com.jolink.omiis.wechat.util.DateUtil;

@Service
public class CheckSessionTimeoutJob {

	private static Logger logger = LoggerFactory.getLogger(CheckSessionTimeoutJob.class);

	@Autowired
	WeChatServiceApiUtil serviceUtil;

	@Scheduled(cron = "0/30 * * * * ?")
	public void doJob() {
		long t1 = System.currentTimeMillis();
		Map<String, String> timeoutSessions = serviceUtil.getSessionManager().getTimeoutSessionList();
		logger.info("开始清理超时会话，超时会话列表：{}。", timeoutSessions);
		for (Iterator<String> it = timeoutSessions.keySet().iterator(); it.hasNext();) {
			String key = it.next();
			String openId = key;
			String value = timeoutSessions.get(key);
			StringBuffer content = new StringBuffer();
			Map<String, String> userBaseInfo = new HashMap<String, String>();
			Map<String, String> userSessionInfo = new HashMap<String, String>();
			String appId = null;
			String sessionId = null;
			try {
				userBaseInfo = serviceUtil.getRedisProcessor().hgetall(CacheUtil.getUserKey(openId));
				logger.info("获取微信用户：{}，基本信息：{}。", openId, userBaseInfo);
				sessionId = userBaseInfo.get("session_id");
				if (StringUtils.isEmpty(sessionId)) {
					logger.error("微信用户：{}的sessionId不存在，可能发生异常情况，后续操作中断。", openId);
					continue;
				}
				userSessionInfo.putAll(serviceUtil.getRedisProcessor().hgetall(CacheUtil.getSessionKey(sessionId)));
				appId = userBaseInfo.get("app_id");
				logger.info("开始清理超时会话：微信用户：{}，基本信息：{}，会话信息：{}。", openId, userBaseInfo, userSessionInfo);
			} catch (Exception e) {
				logger.error(e.getMessage(), e);
			}
			if ("1".equals(value)) {
				try {
					content.append(serviceUtil.getExpression().getCustomerTimeout2());
					logger.info("开始处理微信用户：{}超时未回复，超时状态：{}，超时结束会话提示信息：{}。", openId, value, content.toString());
					String conversation_type = userSessionInfo.get("conversation_type");
					if (ConversationType.SATISFACTION_SURVEY.getValue().equals(conversation_type)) {
						String result = serviceUtil.getRedisProcessor().hdel(CacheUtil.getUserKey(openId),
								"session_id");
						String host = serviceUtil.getConfiguration().getString("OMIIS_SERVER_HOST", "localhost");
						String uri = "http://" + host + ":7003/modifyinfo/logconversation/overtime";
						List<NameValuePair> formData = new ArrayList<>();
						formData.add(new BasicNameValuePair("conversationId", userSessionInfo.get("conversationId")));
						formData.add(new BasicNameValuePair("isOvertime", "1"));
						UrlEncodedFormEntity urlEncodeFormEntity = new UrlEncodedFormEntity(formData, HTTP.UTF_8);
						try {
							String retResult = (String) serviceUtil.getHttpHandler().post2(uri, "",
									urlEncodeFormEntity);
							logger.info("更新微信用户：{}，更新内容：{}，操作结果：{}。", uri, urlEncodeFormEntity.toString(), retResult);
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
						}
						logger.info("微信用户：{}，限定时间内用户未做满意度评价，修改超时结果，清除本次会话，操作结果：{}。", openId, result);
					} else if (ConversationType.NO_REPLAY_NOTIFICATION.getValue().equals(conversation_type)
							|| ConversationType.EVENT_WAITING_REPLY.getValue().equals(conversation_type)
							|| ConversationType.EVENT_WAITING.getValue().equals(conversation_type)) {
						String result = serviceUtil.getRedisProcessor().hdel(CacheUtil.getUserKey(openId),
								"session_id");
						String message = CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
								MessageType.TEXT.getValue(),
								new String[] { serviceUtil.getExpression().getAgentTimeoutTip2() });
						Map<String, String> msg = new HashMap<String, String>(userSessionInfo);
						{
							// msg.put("user_id",
							// userSessionInfo.get("user_id"));
							// msg.put("msgContent",
							// serviceUtil.getExpression().getAgentTimeoutTip2());
							// msg.put("msgType",
							// ConversationType.TEXT.toString());
							// msg.put("senderRole",
							// SenderRole.AGENT.getValue().toUpperCase());
							// serviceUtil.getOmiisMessager().sendMessage(msg);
							// msg.remove("senderRole");
						}
						logger.info("微信用户：{}，未回复是否继续等待，由系统结束本次会话，提示信息：{}，操作结果：{}。", openId, message, result);
						// update by wangyq 20161101
						// 根据appid是否为空判断发送目标，客服接口、公众号服务器
						if (StringUtils.isEmpty(appId)) {
							IWeChatBrokerMessage broker = SpringContextUtil.getBean(IWeChatBrokerMessage.class);
							broker.response(message);
						} else {
							serviceUtil.getCustomerService().send(userSessionInfo.get("app_id"), message);
						}
						msg.putAll(userSessionInfo);
						if (ConversationType.EVENT_WAITING_REPLY.getValue().equals(conversation_type)
								|| ConversationType.EVENT_WAITING.getValue().equals(conversation_type)) {
							msg.put("msgType", ConversationType.DISCONNECT.getValue().toUpperCase());
						} else {
							msg.put("msgType", ConversationType.HANGUP.getValue().toUpperCase());
							msg.put("senderRole", SenderRole.AGENT.getValue().toUpperCase());
						}

						String host = serviceUtil.getConfiguration().getString("OMIIS_SERVER_HOST", "localhost");
						String uri = "http://" + host + ":7003/modifyinfo/logconversation/overtime";
						List<NameValuePair> formData = new ArrayList<>();
						formData.add(new BasicNameValuePair("conversationId", userSessionInfo.get("conversationId")));
						formData.add(new BasicNameValuePair("isOvertime", "1"));
						UrlEncodedFormEntity urlEncodeFormEntity = new UrlEncodedFormEntity(formData, HTTP.UTF_8);
						logger.info("调用全媒体接口:{},更新超时结果：{}。", uri, urlEncodeFormEntity.toString());
						try {
							serviceUtil.getHttpHandler().post2(uri, "", urlEncodeFormEntity);
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
						}

						msg.put("user_id", userSessionInfo.get("user_id"));
						logger.info("通知Bus断开与微信用户：{}的连接。", openId);
						serviceUtil.getOmiisMessager().sendMessage(msg);
						logger.info("微信用户：{}，会话信息：{}，限定时间内用户未做是否继续等待回复，系统自动终止其会话，发送断开与坐席的连接请求：{}。", openId,
								userSessionInfo, msg);
					} else {
						try {
							String message = CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
									MessageType.TEXT.getValue(), new String[] { content.toString() });
							try {
								userSessionInfo.put("conversation_type", ConversationType.HANGUP.toString());
								serviceUtil.getRedisProcessor().hmset(CacheUtil.getSessionKey(sessionId),
										userSessionInfo);
								Map<String, String> msg = new HashMap<String, String>(userSessionInfo);
								msg.putAll(userSessionInfo);
								{
									// 发送超时结束语至座席
									// msg.put("msgType",
									// ConversationType.TEXT.toString());
									// msg.put("user_id",
									// userSessionInfo.get("user_id"));
									// msg.put("msgContent",
									// content.toString());
									// msg.put("senderRole",
									// SenderRole.AGENT.getValue().toUpperCase());
									// serviceUtil.getOmiisMessager().sendMessage(msg);
								}
								msg.remove("senderRole");
								msg.put("msgType", ConversationType.HANGUP.toString());
								serviceUtil.getRedisProcessor().srem(userSessionInfo.get("receiverId"), openId);
								serviceUtil.getOmiisMessager().sendMessage(msg);
								logger.info("微信用户：{}，会话信息：{}，由于长时间未回复，系统自动终止其与坐席：{}的会话，发送断开与坐席的连接请求：{}。", openId,
										userSessionInfo, userSessionInfo.get("receiverId"), msg);
							} catch (Exception e) {
								logger.error(e.getMessage(), e);
							}
							{
								String host = serviceUtil.getConfiguration().getString("OMIIS_SERVER_HOST",
										"localhost");
								String uri = "http://" + host + ":7003/modifyinfo/logconversation/overtime";
								List<NameValuePair> formData = new ArrayList<>();
								formData.add(new BasicNameValuePair("conversationId",
										userSessionInfo.get("conversationId")));
								formData.add(new BasicNameValuePair("isOvertime", "1"));
								UrlEncodedFormEntity urlEncodeFormEntity = new UrlEncodedFormEntity(formData,
										HTTP.UTF_8);
								String result = (String) serviceUtil.getHttpHandler().post2(uri, "",
										urlEncodeFormEntity);
								logger.info("调用全媒体接口:{},更新内容：{}，操作结果：{}。", uri, urlEncodeFormEntity.toString(), result);
							}

							// update by wangyq 20161101
							// 根据appid是否为空判断发送目标，客服接口、公众号服务器
							if (StringUtils.isEmpty(appId)) {
								IWeChatBrokerMessage broker = SpringContextUtil.getBean(IWeChatBrokerMessage.class);
								broker.response(message);
							} else {
								serviceUtil.getCustomerService().send(userSessionInfo.get("app_id"), message);
								logger.info("发送微信用户：{}，超时结束会话提示信息：{}。", openId, message);
							}

							if (!userSessionInfo.containsKey("session_valid_flag")) {
								serviceUtil.getSessionManager().removeSession(openId);
								serviceUtil.getRedisProcessor().hdel(CacheUtil.getUserKey(openId), "session_id");
								// TODO 是否解除与座席的绑定关系
								logger.info("微信用户：{}未发送，会话内容：{}，达到超时结束会话阀值，不发送满意度，清除会话信息。", openId, userSessionInfo);
								return;
							}

							String satisfactionSurveyMessage = serviceUtil.getExpression()
									.getSatisfactionSurveyMessage();
							userBaseInfo.putAll(serviceUtil.getRedisProcessor().hgetall(CacheUtil.getUserKey(openId)));
							userSessionInfo.putAll(
									serviceUtil.getRedisProcessor().hgetall(CacheUtil.getSessionKey(sessionId)));
							userSessionInfo.put("conversation_type", ConversationType.SATISFACTION_SURVEY.getValue());
							serviceUtil.getRedisProcessor().hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
							serviceUtil.getCustomerService().send(userBaseInfo.get("app_id"), CSMessageBuilder
									.createMessage(openId, MessageType.TEXT.getValue(), satisfactionSurveyMessage));

							// 20161213 update by wangyq
							{
								Map<String, String> deltaSessionInfo = new HashMap<String, String>();
								deltaSessionInfo.put("openId", openId);
								deltaSessionInfo.put("agentId", userSessionInfo.get("receiverId"));
								deltaSessionInfo.put("direction", "agent");
								deltaSessionInfo.put("agent_previous_message_timestamp",
										DateUtil.getCurrentTimeMillis());
								deltaSessionInfo.put("customer_previous_message_timestamp",
										deltaSessionInfo.get("agent_previous_message_timestamp"));
								serviceUtil.getSessionManager().updateSession(openId, deltaSessionInfo);
							}
							logger.info("设置微信用户：{}满意度评价状态为未评价。", openId);
							try {
								String host = serviceUtil.getConfiguration().getString("OMIIS_SERVER_HOST",
										"localhost");
								String uri = "http://" + host + ":7003/modifyinfo/investigation/update";
								List<NameValuePair> formData = new ArrayList<>();
								formData.add(new BasicNameValuePair("conversationId",
										userSessionInfo.get("conversationId")));
								formData.add(new BasicNameValuePair("grade", "NO_JUDGE"));
								UrlEncodedFormEntity urlEncodeFormEntity = new UrlEncodedFormEntity(formData,
										HTTP.UTF_8);
								String result = (String) serviceUtil.getHttpHandler().post2(uri, "",
										urlEncodeFormEntity);
								logger.info("更新微信用户：{}满意度为未评价，更新内容：{}，操作结果：{}。", openId, urlEncodeFormEntity, result);
							} catch (Exception e) {
								logger.error(e.getMessage(), e);
							}
							logger.info("推送满意度评价至微信用户：{}，同时更新会话信息：{}，通知内容：{}。", openId, userSessionInfo,
									satisfactionSurveyMessage);
						} catch (Exception e) {
							logger.error(e.getMessage(), e);
						}
						continue;
					}
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
			} else if ("2".equals(value)) {
				String conversation_type = userSessionInfo.get("conversation_type");
				logger.info("处理微信用户：{}短时间未回复，超时状态：{}，会话状态：{}。", openId, value, conversation_type);
				if (ConversationType.RESOURCE_REQUEST.getValue().equals(conversation_type)
						|| ConversationType.SATISFACTION_SURVEY.getValue().equals(conversation_type)
						|| ConversationType.NO_REPLAY_NOTIFICATION.getValue().equals(conversation_type)
						|| ConversationType.EVENT_WAITING.getValue().equals(conversation_type)
						|| ConversationType.EVENT_WAITING_REPLY.getValue().equals(conversation_type)) {
					continue;
				}
				try {
					serviceUtil.getRedisProcessor().hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
				String message = CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
						MessageType.TEXT.getValue(),
						new String[] { serviceUtil.getExpression().getCustomerTimeout1() });
				// update by wangyq 20161101
				// 根据appid是否为空判断发送目标，客服接口、公众号服务器
				if (StringUtils.isEmpty(appId)) {
					IWeChatBrokerMessage broker = SpringContextUtil.getBean(IWeChatBrokerMessage.class);
					broker.response(message);
				} else {
					serviceUtil.getCustomerService().send(userSessionInfo.get("app_id"), message);
					logger.info("发送微信用户：{}，短时间未回复提示信息：{}。", openId, message);
				}
			} else if ("3".equals(value)) {
				logger.info("通知微信用户：{}坐席长时间未回复，是否由客户主动结束对话，超时状态：{}。", openId, value);
				String message = null;
				try {
					String conversationType = userSessionInfo.get("conversation_type");
					if (ConversationType.EVENT_WAITING.getValue().equals(conversationType)) {
						userSessionInfo.put("conversation_type", ConversationType.EVENT_WAITING_REPLY.getValue());
						message = CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
								MessageType.TEXT.getValue(),
								new String[] { serviceUtil.getExpression().getQueueTimeoutTip() });
					} else {
						message = CSMessageBuilder.createMessage(userSessionInfo.get("open_id"),
								MessageType.TEXT.getValue(),
								new String[] { serviceUtil.getExpression().getAgentTimeoutTip() });
						userSessionInfo.put("conversation_type", ConversationType.NO_REPLAY_NOTIFICATION.getValue());
					}
					logger.info("发送微信用户：{}，会话信息：{}，坐席未回复提示信息：{},同时更新会话信息。", openId, userSessionInfo, message);
					serviceUtil.getRedisProcessor().hmset(CacheUtil.getSessionKey(sessionId), userSessionInfo);
				} catch (Exception e) {
					logger.error(e.getMessage(), e);
				}
				// TODO 20161214 update by wangyq，不确定这么做是否ok？
				Map<String, String> deltaSessionInfo = new HashMap<String, String>();
				deltaSessionInfo.put("openId", openId);
				deltaSessionInfo.put("direction", "agent");
				deltaSessionInfo.put("agent_previous_message_timestamp", DateUtil.getCurrentTimeMillis());
				serviceUtil.getSessionManager().updateSession(openId, deltaSessionInfo);
				// update by wangyq 20161101
				// 根据appid是否为空判断发送目标，客服接口、公众号服务器
				if (StringUtils.isEmpty(appId)) {
					IWeChatBrokerMessage broker = SpringContextUtil.getBean(IWeChatBrokerMessage.class);
					broker.response(message);
				} else {
					serviceUtil.getCustomerService().send(userSessionInfo.get("app_id"), message);
				}
			}
		}
		long t2 = System.currentTimeMillis();
		logger.info("清理超时会话完成，耗时：{}毫秒。", (t2 - t1));
	}
}
